package top.xiangqifu.springboot2.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.xiangqifu.springboot2.user.base.BaseDataResult;
import top.xiangqifu.springboot2.user.base.BasePageResult;
import top.xiangqifu.springboot2.user.base.BaseResult;
import top.xiangqifu.springboot2.user.base.PageBean;
import top.xiangqifu.springboot2.user.dao.*;
import top.xiangqifu.springboot2.user.entity.*;
import top.xiangqifu.springboot2.user.exception.AppException;
import top.xiangqifu.springboot2.user.service.AuthService;
import top.xiangqifu.springboot2.user.utils.AuthInfoUtils;
import top.xiangqifu.springboot2.user.utils.JwtUtils;
import top.xiangqifu.springboot2.user.utils.Utils;
import top.xiangqifu.springboot2.user.vo.UserInfo;


import java.util.List;
import java.util.UUID;

@Slf4j
@Service
@RequiredArgsConstructor
public class AuthServiceImpl implements AuthService {
    private final TbUserDAO tbUserDAO;
    private final TbUserInfoDAO tbUserInfoDAO;
    private final TbRoleDAO tbRoleDAO;
    private final TbRoleActionsDAO tbRoleActionsDAO;
    private final TbActionsDAO tbActionsDAO;


    @Override
    public BaseDataResult<UserInfo> getLoginUser() {
        AuthInfo authInfo = AuthInfoUtils.authInfo();
        if (authInfo.getUid() == null) {
            return BaseDataResult.failNoData("用户未登录");
        }
        UserInfo userInfo =queryById(authInfo.getUid());
        if(userInfo==null) {
            return BaseDataResult.failNoData("用户不存在");
        }
        return BaseDataResult.ok(userInfo.viewData());
    }




    @Override
    public UserInfo queryById(Integer uid) {
        UserInfo userInfo = new UserInfo();
        TbUser tbUser = tbUserDAO.selectById(uid);
        if (tbUser == null) {
            return null;
        }
        userInfo.setTbUser(tbUser);
        TbRole tbRole = tbRoleDAO.selectById(tbUser.getRole());
        userInfo.setTbRole(tbRole);
        TbUserInfo tbUserInfo = tbUserInfoDAO.selectById(tbUser.getUid());
        userInfo.setTbUserInfo(tbUserInfo);
        return userInfo;
    }

    @Override
    @Transactional
    public BaseResult reg(TbUser tbUser) {
        // 校验用户是否存在
        TbUser check = tbUserDAO.queryByName(tbUser.getUsername());
        if (check != null) {
            return BaseResult.fail("用户名已存在");
        }
        // 密码相关数据
        tbUser.setSalt(Utils.makeSalt());
        tbUser.setPassword(Utils.saltMd5(tbUser.getPassword(), tbUser.getSalt()));
        // 开发者id
        tbUser.setAccessId(UUID.randomUUID().toString());
        tbUser.setAccessKey(UUID.randomUUID().toString());
        // 默认是用户角色
        tbUser.setRole(AuthService.ROLE_USER);
        // 添加主表
        int count = tbUserDAO.insert(tbUser);
        if (count != 1) {
            throw AppException.getInstance("注册失败");
        }
        // 添加附加信息吧
        TbUserInfo tbUserInfo = new TbUserInfo();
        tbUserInfo.setUid(tbUser.getUid());
        tbUserInfo.setCipher(UUID.randomUUID().toString());
        count = tbUserInfoDAO.insert(tbUserInfo);
        if (count != 1) {
            throw AppException.getInstance("注册失败，附件信息无法添加");
        }
        return BaseResult.ok("添加成功");
    }



    @Override
    public boolean checkAuth() {
        // 检查当前用户是否拥有路径访问权限
        AuthInfo authInfo = AuthInfoUtils.authInfo();
        // 查询当前访问路径是否被数据库管理
        QueryWrapper<TbActions> aqw = new QueryWrapper<>();
        aqw.eq("url", authInfo.getMappingPath());
        aqw.eq("method", authInfo.getMethod());
        TbActions actions = tbActionsDAO.selectOne(aqw);
        if (actions == null) {
            // 不被管理的路径直接通过
            return true;
        }
        log.debug("被管理的api：{}", actions);
        if (authInfo.getUid() == null) {
            // 请求中没有登录用户的信息
            return false;
        }
        // 获取用户信息
        TbUser tbUser = tbUserDAO.selectById(authInfo.getUid());
        if (tbUser == null) {
            // 请求中id不正确
            return false;
        }
        // 校验角色是否拥有菜单
        QueryWrapper<TbRoleActions> raqw = new QueryWrapper<>();
        raqw.eq("rid", tbUser.getRole());
        raqw.eq("aid", actions.getAid());
        TbRoleActions tbRoleActions = tbRoleActionsDAO.selectOne(raqw);
        if (tbRoleActions == null) {
            // 没有记录就没有通过授权
            return false;
        }
        return true;
    }

    @Override
    public BaseResult login(TbUser user) {
        // 判断用户是否存在
        TbUser check = tbUserDAO.queryByName(user.getUsername());
        if (check == null) {
            return BaseResult.fail("用户不存在");
        }
        // 判断用户是否禁用
        if ("y".equalsIgnoreCase(check.getDeleted())) {
            return BaseResult.fail("用户已禁用");
        }
        // 校验密码
        String pwd = Utils.saltMd5(user.getPassword(), check.getSalt());
        if (!check.getPassword().equalsIgnoreCase(pwd)) {
            return BaseResult.fail("密码错误");
        }
        // 用登录用户id生成jwt的token
        String token = JwtUtils.makeUserIdToken(check.getUid());
        BaseResult result = BaseResult.ok("登录成功");
        // 递交token给客户端
        result.setToken(token);
        return result;
    }

    @Override
    public BasePageResult<List<TbUser>> queryDelete(String deleted, PageBean pageBean){
        IPage<TbUser> page = pageBean.toPage(TbUser.class);
        List<TbUser> list=tbUserDAO.queryDeleted(deleted);
        pageBean.buildPageInfo(page);
        return BasePageResult.ok(pageBean, list);
    }

    @Override
    public BaseResult update(TbUser user){
        int i = tbUserDAO.updateDeleted(user);
        return i == 1 ? BaseResult.ok("成功解冻") : BaseResult.fail("解冻失败，请稍后重试");
    }

    @Override
    public BaseResult delete(Integer id){
        if (id==1){
            return BaseResult.fail("超级管理员不能删除");
        }
        int i = tbUserDAO.deleteById(id);
        return i == 1 ? BaseResult.ok("删除信息成功") : BaseResult.fail("删除信息失败，请稍后重试");
    }
}
